/*
设置自动开关机时间，如果第一位数字是0，则设置关机时间，数字是1设置开机时间。
Topic:POT/Set，message：“0,2048”设置关机时间为20：48；“1,1024”设置开机时间10：24
Topic:POT/Switch，message：“1，1，1”，电源按键动作一次，温度调节动作一次，设置自动开关机状态为启用
内存分配如下
0：关机时间
1：开机时间
2：自动开关机状态
*/
#include <ESP8266WiFi.h>
#include <WiFiManager.h>
#include <PubSubClient.h>
// char mqtt_server[] = "h3253k9765.oicp.vip";
//  char mqtt_server[] = "lubo1982.myqnapcloud.cn";
const char *mqtt_server = "192.168.3.254";
const char *mqttUser = "lu";
const char *mqttPassWd = "5891381";
const int port = 1883;
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (150)
// 电源按键输入
#define P_KEY_IN 14
// 电源按键输出
#define P_KEY_OUT 0
// 设置温度
#define S_KEY 2
// 温度指示，45度
#define LED_T45 13
#define PW_ON_TIME 1
#define PW_OFF_TIME 0
#define ON 1
#define OFF 0
uint8_t macAddr[6];
String Host;
char msg[MSG_BUFFER_SIZE];
struct
{
    bool swStatus; // 当前水壶状态，1为开机，0为关机
    int potSetTemp;
} PotStatus;

void checkPotSwStatus()
{
    Serial.print("Check Pot power status -- ");
    PotStatus.swStatus = OFF;
    for (int tmp = 0; tmp < 3; tmp++)
    {
        tempButtonPress();
        delay(50);
        // 如果45度的灯亮则退出循环，设置状态为已经开机，不执行按钮按键动作
        if (digitalRead(LED_T45))
        {

            PotStatus.swStatus = ON;
            if (tmp == 0)
                PotStatus.potSetTemp = 85;
            else if (tmp == 1)
                PotStatus.potSetTemp = 55;
            else
                PotStatus.potSetTemp = 45;
        }
    }
}
void PublishPotSwStatus()
{
    client.publish("POT/HA", (PotStatus.swStatus == 1 ? "1" : "0"));
    Serial.println((PotStatus.swStatus == 1 ? "On" : "Off"));
}
void powerOn()
{
    Serial.println("Power on the POT");
    checkPotSwStatus();
    if (PotStatus.swStatus == OFF)
    {
        powerButtonPress();
        PotStatus.swStatus = ON;
    }
    PublishPotSwStatus();
    setPotTemp45();
}
void powerOff()
{
    Serial.println("Power off the POT");
    checkPotSwStatus();
    if (PotStatus.swStatus == ON)
    {
        powerButtonPress();
        PotStatus.swStatus = OFF;
    }
    PublishPotSwStatus();
}
void setPotTemp45()
{
    for (int tmp = 0; tmp < 4; tmp++)
    {
        if (digitalRead(LED_T45))
        {
            break;
        }
        else
        {
            tempButtonPress();
            delay(50);
        }
    }
}
void powerButtonPress()
{
    Serial.println("Pressed Power buttun!");
    digitalWrite(P_KEY_OUT, 0);
    delay(100);
    digitalWrite(P_KEY_OUT, 1);

    if (PotStatus.swStatus == 1)
        PotStatus.swStatus = 0;
    else
        PotStatus.swStatus = 1;
}
void tempButtonPress()
{
    Serial.println("Pressed Temp set buttun!");
    digitalWrite(S_KEY, 0);
    delay(100);
    digitalWrite(S_KEY, 1);
}

void callback(char *topic, byte *payload, unsigned int length)
{
    String message, top;
    int powerButton, tempButton, autoMode, OTAOrder;
    int setState, setTime; // serState是设置开机时间还是关机时间。0是关机时间，1是开机时间

    top = topic;

    for (int i = 0; i < length; i++)
    {
        message += (char)payload[i];
    }
    Serial.printf("R:[%s] %s\n", top.c_str(), message.c_str());
    // 直接控制水壶按键,并设置自动开关机状态。
    if (top == "POT/Switch")
    {

        if (payload[0] == '1')
        {
            powerOn();
            client.publish("POT/Switch", "", 1);
        }
        else if (payload[0] == '2')
        {
            powerOff();
            client.publish("POT/Switch", "", 1);
        }
    }
    // 设置自动开关机时间，如果第一位数字是0，则设置关机时间，数字是1设置开机时间。
}
// 与MQTT服务器断线后进行重联，
void reconnect()
{
    // Loop until we're reconnected
    while (!client.connected())
    {
        Serial.print("Attempting MQTT connection...");
        // Create a random client ID
        String clientId = "ESP8266Client-";
        clientId += String(random(0xffff), HEX);
        // Attempt to connect
        if (client.connect(clientId.c_str(), "lu", "5891381"))
        {
            Serial.println("connected");
            // Once connected, publish an announcement...
            client.publish("outTopic", "hello world");
            // ... and resubscribe
            client.subscribe("inTopic");
        }
        else
        {
            Serial.print("failed, rc=");
            Serial.print(client.state());
            Serial.println(" try again in 5 seconds");
            // Wait 5 seconds before retrying
            delay(5000);
        }
    }
    subScribe();
}
// 订阅
void subScribe()
{
    client.subscribe("POT/Switch");
}
void setup()
{
    Serial.begin(115200);
    pinMode(P_KEY_IN, INPUT);
    pinMode(12, INPUT);
    pinMode(LED_T45, INPUT);
    pinMode(P_KEY_OUT, OUTPUT_OPEN_DRAIN);
    pinMode(S_KEY, OUTPUT_OPEN_DRAIN);
    pinMode(15, OUTPUT);
    PotStatus.swStatus = OFF;
    WiFiManager wifiManager;
    wifiManager.setTimeout(180);
    WiFi.macAddress(macAddr);
    Host = "POT-" + macAddr[4] + macAddr[5];
    if (!wifiManager.autoConnect("AutoConnect-POT"))
    {
        Serial.println("failed to connect and hit timeout");
    }
    else
    {
        Serial.println("connected...yeey :)");
        powerOn();
        for (int i = 0; i < 6; i++)
        {
            powerButtonPress();
            //   delay(100);
        }
        powerOff();
    }
    WiFi.hostname(Host.c_str());
    // MQTT
    client.setServer(mqtt_server, port);
    client.setCallback(callback);
    reconnect();
    digitalWrite(0, 1);
    digitalWrite(S_KEY, 1);
}
void loop()
{
    int actTime;
    int pressTime = 0;
    unsigned long now = millis();
    if (!client.connected())
    {
        reconnect();
    }
    client.loop();
    if (digitalRead(P_KEY_IN) == 0)
    {
        while (digitalRead(P_KEY_IN) == 0)
        {
            pressTime++;
            delay(100);
            if (pressTime > 20)
                break;
        }
        if (pressTime > 20)
        {
            Serial.println("Power on/off");
            // tempButtonPress();
            powerButtonPress();
            checkPotSwStatus();
            setPotTemp45();
            //   PublishPotSwStatus();
            while (digitalRead(P_KEY_IN) == 0)
                delay(50);
        }
    }
    if (now - lastMsg > 2000)
    {
        lastMsg = now;
        // 可读信息

        Serial.print("T:[POT/HA]");
        Serial.println((PotStatus.swStatus == 1 ? "1" : "0"));
        client.publish("POT/HA", (PotStatus.swStatus == 1 ? "1" : "0"));
    }
}
